﻿namespace Pathfinding
{
    using Pathfinding.Util;
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using UnityEngine;

    public class NavmeshAdd : MonoBehaviour
    {
        private static List<NavmeshAdd> allCuts = new List<NavmeshAdd>();
        private Bounds bounds;
        public Vector3 center;
        public static readonly Color GizmoColor = new Color(0.3686275f, 0.9372549f, 0.145098f);
        public Mesh mesh;
        public float meshScale = 1f;
        public Vector2 rectangleSize = new Vector2(1f, 1f);
        protected Transform tr;
        private int[] tris;
        public MeshType type;
        public bool useRotation;
        private Vector3[] verts;

        private static void Add(NavmeshAdd obj)
        {
            allCuts.Add(obj);
        }

        public void Awake()
        {
            Add(this);
        }

        public static List<NavmeshAdd> GetAll()
        {
            return allCuts;
        }

        public static List<NavmeshAdd> GetAllInRange(Bounds b)
        {
            List<NavmeshAdd> list = ListPool<NavmeshAdd>.Claim();
            for (int i = 0; i < allCuts.Count; i++)
            {
                if (allCuts[i].enabled && Intersects(b, allCuts[i].GetBounds()))
                {
                    list.Add(allCuts[i]);
                }
            }
            return list;
        }

        public Bounds GetBounds()
        {
            switch (this.type)
            {
                case MeshType.Rectangle:
                    if (this.useRotation)
                    {
                        Matrix4x4 matrixx = Matrix4x4.TRS(this.tr.position, this.tr.rotation, Vector3.one);
                        this.bounds = new Bounds(matrixx.MultiplyPoint3x4(this.center + ((Vector3) (new Vector3(-this.rectangleSize.x, 0f, -this.rectangleSize.y) * 0.5f))), Vector3.zero);
                        this.bounds.Encapsulate(matrixx.MultiplyPoint3x4(this.center + ((Vector3) (new Vector3(this.rectangleSize.x, 0f, -this.rectangleSize.y) * 0.5f))));
                        this.bounds.Encapsulate(matrixx.MultiplyPoint3x4(this.center + ((Vector3) (new Vector3(this.rectangleSize.x, 0f, this.rectangleSize.y) * 0.5f))));
                        this.bounds.Encapsulate(matrixx.MultiplyPoint3x4(this.center + ((Vector3) (new Vector3(-this.rectangleSize.x, 0f, this.rectangleSize.y) * 0.5f))));
                    }
                    else
                    {
                        this.bounds = new Bounds(this.tr.position + this.center, new Vector3(this.rectangleSize.x, 0f, this.rectangleSize.y));
                    }
                    break;

                case MeshType.CustomMesh:
                    if (this.mesh != null)
                    {
                        Bounds bounds = this.mesh.bounds;
                        if (this.useRotation)
                        {
                            Matrix4x4 matrixx2 = Matrix4x4.TRS(this.tr.position, this.tr.rotation, (Vector3) (Vector3.one * this.meshScale));
                            this.bounds = new Bounds(matrixx2.MultiplyPoint3x4(this.center + bounds.center), Vector3.zero);
                            Vector3 max = bounds.max;
                            Vector3 min = bounds.min;
                            this.bounds.Encapsulate(matrixx2.MultiplyPoint3x4(this.center + new Vector3(max.x, min.y, max.z)));
                            this.bounds.Encapsulate(matrixx2.MultiplyPoint3x4(this.center + new Vector3(min.x, min.y, max.z)));
                            this.bounds.Encapsulate(matrixx2.MultiplyPoint3x4(this.center + new Vector3(min.x, max.y, min.z)));
                            this.bounds.Encapsulate(matrixx2.MultiplyPoint3x4(this.center + new Vector3(max.x, max.y, min.z)));
                        }
                        else
                        {
                            Vector3 size = (Vector3) (bounds.size * this.meshScale);
                            this.bounds = new Bounds((base.transform.position + this.center) + ((Vector3) (bounds.center * this.meshScale)), size);
                        }
                    }
                    break;
            }
            return this.bounds;
        }

        public void GetMesh(Int3 offset, ref Int3[] vbuffer, out int[] tbuffer)
        {
            if (this.verts == null)
            {
                this.RebuildMesh();
            }
            if (this.verts == null)
            {
                tbuffer = new int[0];
            }
            else
            {
                if ((vbuffer == null) || (vbuffer.Length < this.verts.Length))
                {
                    vbuffer = new Int3[this.verts.Length];
                }
                tbuffer = this.tris;
                if (this.useRotation)
                {
                    Matrix4x4 matrixx = Matrix4x4.TRS(this.tr.position + this.center, this.tr.rotation, (Vector3) (this.tr.localScale * this.meshScale));
                    for (int i = 0; i < this.verts.Length; i++)
                    {
                        vbuffer[i] = offset + ((Int3) matrixx.MultiplyPoint3x4(this.verts[i]));
                    }
                }
                else
                {
                    Vector3 vector = this.tr.position + this.center;
                    for (int j = 0; j < this.verts.Length; j++)
                    {
                        vbuffer[j] = offset + ((Int3) (vector + (this.verts[j] * this.meshScale)));
                    }
                }
            }
        }

        private static bool Intersects(Bounds b1, Bounds b2)
        {
            Vector3 min = b1.min;
            Vector3 max = b1.max;
            Vector3 vector3 = b2.min;
            Vector3 vector4 = b2.max;
            return ((((min.x <= vector4.x) && (max.x >= vector3.x)) && (min.z <= vector4.z)) && (max.z >= vector3.z));
        }

        public void OnDestroy()
        {
            Remove(this);
        }

        public void OnEnable()
        {
            this.tr = base.transform;
        }

        [ContextMenu("Rebuild Mesh")]
        public void RebuildMesh()
        {
            if (this.type == MeshType.CustomMesh)
            {
                if (this.mesh == null)
                {
                    this.verts = null;
                    this.tris = null;
                }
                else
                {
                    this.verts = this.mesh.vertices;
                    this.tris = this.mesh.triangles;
                }
            }
            else
            {
                if (((this.verts == null) || (this.verts.Length != 4)) || ((this.tris == null) || (this.tris.Length != 6)))
                {
                    this.verts = new Vector3[4];
                    this.tris = new int[6];
                }
                this.tris[0] = 0;
                this.tris[1] = 1;
                this.tris[2] = 2;
                this.tris[3] = 0;
                this.tris[4] = 2;
                this.tris[5] = 3;
                this.verts[0] = new Vector3(-this.rectangleSize.x * 0.5f, 0f, -this.rectangleSize.y * 0.5f);
                this.verts[1] = new Vector3(this.rectangleSize.x * 0.5f, 0f, -this.rectangleSize.y * 0.5f);
                this.verts[2] = new Vector3(this.rectangleSize.x * 0.5f, 0f, this.rectangleSize.y * 0.5f);
                this.verts[3] = new Vector3(-this.rectangleSize.x * 0.5f, 0f, this.rectangleSize.y * 0.5f);
            }
        }

        private static void Remove(NavmeshAdd obj)
        {
            allCuts.Remove(obj);
        }

        public Vector3 Center
        {
            get
            {
                return (this.tr.position + (!this.useRotation ? this.center : this.tr.TransformPoint(this.center)));
            }
        }

        public enum MeshType
        {
            Rectangle,
            CustomMesh
        }
    }
}

